﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using System.Web;
using System.Web.Mvc;
using Eking.Framework;
using MeresModeling;
using Newtonsoft.Json.Linq;
using Orchard.Themes;

namespace Meres.Controllers
{
    [Themed]
    public class RelationshipDiagramController : GraphController
    {
        //[Authorize()]
        public PartialViewResult Index()
        {
            return PartialView("RdMainView");
        }

        public JsonResult AddOrUpdateRdJson(RelationDiagram rd)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                dynamic redi = model.Graphs.SingleOrDefault(g => g.Id == rd.Id);
                if (redi == null)
                {
                    redi = new RelationDiagram();
                    model.Graphs.AddObject(redi);
                }

                redi.Name = rd.Name;
                redi.Ext = rd.Ext;

                ((RelationDiagram)redi).Owners.Clear();
                foreach (var person in rd.Owners)
                {
                    var pe = model.People.SingleOrDefault(p => p.Id == person.Id);
                    ((RelationDiagram)redi).Owners.Add(pe);
                }

                model.SaveChanges();
                return GetRdJson(redi.Id);
            }
        }

        private object GetRdViewModel(int rdId)
        {
            var model = MeresMainController.Model;

            var rd = model.Graphs.OfType<RelationDiagram>().Single(g => g.Id == rdId);
            var output = new { rd.Id, rd.Name, Nodes = new List<object>(), Links = new List<object>(), Owners = new List<object>() };
            foreach (var graphNode in rd.GraphNodes)
            {
                var pName = "NONAME";
                if (graphNode.Data != null)
                {
                    var jobj = JObject.Parse(graphNode.Data);
                    var pId = jobj["personId"];
                    if (pId != null)
                    {
                        var chk = int.Parse((string)pId);
                        var person = model.People.SingleOrDefault(p => p.Id == chk);
                        pName = person == null ? pName : person.Name;
                    }
                }

                output.Nodes.Add(MakeRdNodeViewModel(graphNode, pName));
            }

            foreach (var graphLink in rd.GraphLinks)
            {
                output.Links.Add(MakeRdLinkViewModel(graphLink));
            }
            return output;

        }

        public JsonResult GetRdJson(int rdId)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var output = GetRdViewModel(rdId);

                return Json(output, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult GetRdDataListJson(string sidx, string sord, int page, int rows,
                bool _search, string searchField, string searchOper, string searchString)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                var query = (from rd in model.Graphs.OfType<RelationDiagram>()
                             select rd).ToList().Select(rd =>
                                 new
                                 {
                                     id = rd.Id,
                                     cell = new object[]{
                                         rd.Id,
                                         rd.Name,
                                         rd.GraphNodes.Count,
                                         rd.GraphLinks.Count,
                                         "p1, p2, p3",
                                         "o1, o2, o3"+rd.Owners.Aggregate("", (a, b) => a + b.Name),
                                         rd.UpdateTime
                                     }
                                 }).ToList();


                var jsonData = new
                {
                    total = 50, // total page
                    page = 0,
                    records = 100, // total item
                    rows = query
                };

                return Json(jsonData, JsonRequestBehavior.AllowGet);
            }
        }

        public void DeleteRelationDiagram(int rdId)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                var graph = model.Graphs.Single(g => g.Id == rdId);

                // Del Links
                var delObjects = graph.GraphLinks.Cast<object>().ToList();

                // Del Nodes
                delObjects.AddRange(graph.GraphNodes);

                // Del graph
                delObjects.Add(graph);

                delObjects.ForEach(model.DeleteObject);

                model.SaveChanges();
            }
        }

        public void EditRelationDiagram(RelationDiagram rd, string oper)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                var graph = model.Graphs.OfType<RelationDiagram>().Single(g => g.Id == rd.Id);
                if (oper == "del")
                {
                    DeleteRelationDiagram(rd.Id);
                    return;
                }

                graph.UpdateTime = DateTime.Now;
                graph.Name = rd.Name;
                model.SaveChanges();
            }
        }

        public void DeleteRdLink(int linkId)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                var rdLink = model.GraphLinks.Single(l => l.Id == linkId);
                ((RelationDiagram)rdLink.Graph).UpdateTime = DateTime.Now;
                model.DeleteObject(rdLink);

                model.SaveChanges();
            }
        }

        public void DeleteRdNode(int nodeId)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                var rdNode = model.UiDats.OfType<GraphNode>().SingleOrDefault(g => g.Id == nodeId);
                var removal = new List<object>();
                removal.AddRange(rdNode.LeftLinks.ToList());
                removal.AddRange(rdNode.RightLinks.ToList());
                removal.Add(rdNode);

                ((RelationDiagram)rdNode.Graph).UpdateTime = DateTime.Now;

                removal.ForEach(model.DeleteObject);

                model.SaveChanges();
            }
        }

        private static object MakeRdNodeViewModel(GraphNode node, string text = null)
        {
            return new
            {
                rdId = node.Graph.Id,
                node.Data,
                node.X,
                node.Y,
                node.W,
                node.H,
                node.Id,
                node.CHash,
                PersonName = text
            };
        }

        private static object MakeRdLinkViewModel(GraphLink link)
        {
            return new
                       {
                           rdId = link.Graph.Id,
                           link.Id,
                           LeftNodeId = link.LeftNode.Id,
                           RightNodeId = link.RightNode.Id,
                           link.Data
                       };
        }

        public JsonResult AddOrUpdateRdNodeJson(GraphNode input)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                var graph = model.Graphs.OfType<RelationDiagram>().SingleOrDefault(g => g.Id == input.Graph.Id);

                var node = model.UiDats.OfType<GraphNode>().SingleOrDefault(ui => ui.Id == input.Id);
                if (node == null)
                {
                    node = new GraphNode { Data = input.Data };
                    graph.GraphNodes.Add(node);
                }
                CloneUiDat(input, node);

                graph.UpdateTime = DateTime.Now;

                model.SaveChanges();

                return Json(MakeRdNodeViewModel(node), JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult AddRdLinkJson(GraphLink link)
        {
            lock (link)
            {
                using (new TransactionScope(TransactionScopeOption.Suppress))
                {
                    var model = MeresMainController.Model;
                    var graph = model.Graphs.OfType<RelationDiagram>().Single(g => g.Id == link.Graph.Id);
                    var gLink = new GraphLink
                    {
                        Data = link.Data
                    };

                    model.GraphLinks.AddObject(gLink);
                    graph.GraphLinks.Add(gLink);
                    gLink.LeftNode = model.UiDats.OfType<GraphNode>().Single(n => n.Id == link.LeftNode.Id);
                    gLink.RightNode = model.UiDats.OfType<GraphNode>().Single(n => n.Id == link.RightNode.Id);

                    graph.UpdateTime = DateTime.Now;

                    model.SaveChanges();

                    return Json(MakeRdLinkViewModel(gLink), JsonRequestBehavior.AllowGet);
                }
            }
        }

        public PartialViewResult GetListView()
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {

                var query = (from rd in MeresMainController.Model.Graphs.OfType<RelationDiagram>()
                             select rd).ToList().Select(rd =>
                                 new RelationshipDiagramViewModel
                                     {
                                         Id = rd.Id,
                                         Name = rd.Name,
                                         OwnersText = rd.Owners.Aggregate("Owners:", (a, b) => a + b.Name)
                                     }).ToList();

                return PartialView("RdListView", query);
            }
        }

        public PartialViewResult GetDetailView(int rdId)
        {
            return PartialView("RdDetailView");
        }

        public JsonResult GetDetailViewNew(int rdId)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var txt = this.RenderPartialViewToString("RdDetailView");
                return Json(
                    new
                    {
                        ViewModel = GetRdViewModel(rdId),
                        Html = txt
                    }, JsonRequestBehavior.AllowGet);
            }
        }
    }


    [Themed]
    public class GraphController : Controller
    {
        public static void CloneUiDat(UiDat from, UiDat to)
        {
            to.W = from.W;
            to.H = from.H;
            to.X = from.X;
            to.Y = from.Y;
            to.Ext = from.Ext;
            to.CHash = from.CHash;
        }

        public void UpdateUiData(UiDat ui)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var model = MeresMainController.Model;
                var uidat = model.UiDats.Single(u => u.Id == ui.Id);
                CloneUiDat(ui, uidat);
                model.SaveChanges();
            }
        }
    }
    public class RelationshipDiagramViewModel
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string OwnersText { get; set; }
    }
}